﻿/*
-----------------------------------------------------------------------------
This source file is part of Cell Cloud.

Copyright (c) 2009-2012 Cell Cloud Team - cellcloudproject@gmail.com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "CellStableHeaders.h"
#include "CellNucleus.h"
#include "CellPlatformInformation.h"
#include "CellCellet.h"
#include "CellCelletSupervisor.h"
#include "CellContactService.h"
#include "CellCloudGraph.h"
#include "CellEndpoint.h"
#include "CellCryptologyImpl.h"
#include "CellDialectEnumerator.h"
#include "CellDynLib.h"
#include "CellDynLibManager.h"
#include "CellExecutorManager.h"
#include "CellString.h"
#include "CellStringConverter.h"
#include "CellStorageEnumerator.h"
#include "CellSQLiteStorageImpl.h"
#include "CellTalkService.h"
#include "CellPerformance.h"
#include "CellRelationalNucleusAdapter.h"
#include "CellMessageService.h"
#include "CellLoggerManager.h"
#include "CellInet4Address.h"
#include "CellInet6Address.h"
#include "CellCrashReport.h"

namespace cell
{

template<> Nucleus* Singleton<Nucleus>::ms_Singleton = NULL;

//-----------------------------------------------------------------------
Nucleus* Nucleus::getSingletonPtr(void)
{
	return ms_Singleton;
}
//-----------------------------------------------------------------------
Nucleus& Nucleus::getSingleton(void)
{  
	assert(ms_Singleton);
	return (*ms_Singleton);
}

//---------------------------------------------------------------------------
Nucleus::Nucleus(const NucleusConfig& config, const String& logFileName)
	: mTag(RANDOM_UUID)
	, mConfig(config)
	, mCryptology(NULL)
	, mPerformace(NULL)
	, mLoggerManager(NULL)
	, mExecutorManager(NULL)
	, mTalkService(NULL)
	, mDynLibManager(NULL)
	, mCelletSupervisor(NULL)
	, mSpinning(false)
	, mCloudGraph(NULL)
	, mNative(NULL)
	, mStorageEnumerator(NULL)
	, mDialectEnumerator(NULL)
	, mContactService(NULL)
{
	String version = StringConverter::toString(CELL_VERSION_MAJOR) + "." +
		StringConverter::toString(CELL_VERSION_MINOR) + "." +
		StringConverter::toString(CELL_VERSION_REVISION) + 
	#if CELL_ARCH_TYPE == CELL_ARCHITECTURE_32
		" (Build 32bit " +
	#elif CELL_ARCH_TYPE == CELL_ARCHITECTURE_64
		" (Build 64bit " +
	#else
		" (Build ? " +
	#endif
		CELL_VERSION_SUFFIX + " - " + CELL_VERSION_NAME + ")";

	if (LoggerManager::getSingletonPtr() == NULL)
	{
		mLoggerManager = CELL_NEW LoggerManager();
		mLoggerManager->createLogger(logFileName, true, true);
	}

#ifdef CELL_CRASH_REPORT
	mCrashReport = CELL_NEW CrashReport();
	mCrashReport->install();
#endif // CELL_CRASH_REPORT

	String msg("Cell Cloud ");
	msg += version;
	mLoggerManager->log(msg);
	mLoggerManager->log("Nucleus singleton created (" + cell::peek<Nucleus>(this) + ")");
	mLoggerManager->log("Nucleus Tag : " + TAG_TO_STRING(mTag));

	// 初始化 Socket
	initializeSock();

	// 创建加密实用库实例
	mCryptology = CELL_NEW Cryptology();

#if CELL_PLATFORM != CELL_PLATFORM_IOS
	// 创建动态库管理器实例
	mDynLibManager = CELL_NEW DynLibManager();
#endif

	// 创建线程池管理器实例
	mExecutorManager = CELL_NEW ExecutorManager();

	// 创建云图实例
	mCloudGraph = CELL_NEW CloudGraph();

	// 创建 Talk 服务实例
	mTalkService = CELL_NEW TalkService(mCloudGraph);

	// 创建存储枚举实例
	mStorageEnumerator = CELL_NEW StorageEnumerator();

	// 创建方言枚举实例
	mDialectEnumerator = CELL_NEW DialectEnumerator();
}
//-----------------------------------------------------------------------
Nucleus::~Nucleus(void)
{
	mLoggerManager->log("Nucleus singleton destroyed (" + cell::peek<Nucleus>(this) + ")");

	if (NULL != mCelletSupervisor)
	{
		CELL_DELETE mCelletSupervisor;
		mCelletSupervisor = NULL;
	}

	if (NULL != mTalkService)
	{
		CELL_DELETE mTalkService;
		mTalkService = NULL;
	}

	if (NULL != mCloudGraph)
	{
		CELL_DELETE mCloudGraph;
		mCloudGraph = NULL;
	}

	if (NULL != mNative)
	{
		CELL_DELETE mNative;
		mNative = NULL;
	}

	if (NULL != mDynLibManager)
	{
		CELL_DELETE mDynLibManager;
		mDynLibManager = NULL;
	}

	if (NULL != mCryptology)
	{
		CELL_DELETE mCryptology;
		mCryptology = NULL;
	}

	if (NULL != mPerformace)
	{
		CELL_DELETE mPerformace;
		mPerformace = NULL;
	}

	if (NULL != mExecutorManager)
	{
		CELL_DELETE mExecutorManager;
		mExecutorManager = NULL;
	}

	if (NULL != mStorageEnumerator)
	{
		CELL_DELETE mStorageEnumerator;
		mStorageEnumerator = NULL;
	}

	if (NULL != mDialectEnumerator)
	{
		CELL_DELETE mDialectEnumerator;
		mDialectEnumerator = NULL;
	}

	// 停止 Socket
	finalizeSock();

#ifdef CELL_CRASH_REPORT
	if (NULL != mCrashReport)
	{
		CELL_DELETE mCrashReport;
		mCrashReport = NULL;
	}
#endif // CELL_CRASH_REPORT

	if (NULL != mLoggerManager)
	{
		CELL_DELETE mLoggerManager;
		mLoggerManager = NULL;
	}
}
//-----------------------------------------------------------------------
bool Nucleus::startup(void)
{
	mLoggerManager->log("");
	mLoggerManager->log("*-*-* Cell Initializing *-*-*");

#ifdef CELL_CRASH_REPORT
	if (mCrashReport->available())
	{
		mLoggerManager->log("Crash report is available.");
	}
	else
	{
		mLoggerManager->log("Crash report is not available.");
	}
#endif // CELL_CRASH_REPORT

	// 检查并启动为 NODE
	if (mConfig.role & NucleusConfig::NODE)
	{
		// 创建 Cellet Manager 实例
		mCelletSupervisor = CELL_NEW CelletSupervisor();

		// 创建性能监视器实例
		mPerformace = CELL_NEW Performance();

		// 创建联络服务
		mContactService = CELL_NEW ContactService();

		// 启动 Talk 服务
		if (mTalkService->startup())
		{
			// 服务上锁，等待 Cellet 加载完毕
			mTalkService->latch();

			mLoggerManager->log("Talk Service starts successfully");
		}
		else
		{
			mLoggerManager->log("Talk Service starts failed");
		}

		// 加载 Adapter 和 Cellet 库
		loadExternalLib();

		// 激活 Cellet
		activateCellets();

		// 解锁 Talk 服务
		mTalkService->unlatch();
	}

	// 检查并启动为 GATE
	if (mConfig.role & NucleusConfig::GATE)
	{
		if (NULL == mPerformace)
			mPerformace = CELL_NEW Performance();

		if (!mTalkService->prepared())
		{
			// 启动 Talk 服务
			if (mTalkService->startup())
			{
				mLoggerManager->log("Talk Service starts successfully");
			}
			else
			{
				mLoggerManager->log("Talk Service starts unsuccessfully");
			}
		}

		// 启动代理
		mTalkService->startProxy();
	}

	// 检查并启动为 STORAGE
	if (mConfig.role & NucleusConfig::STORAGE)
	{
		// TODO
	}

	// 检查并启动为 CONSUMER
	if (mConfig.role & NucleusConfig::CONSUMER)
	{
		// 启动维护任务
		mTalkService->startSchedule();
	}

	if (NULL != mPerformace)
	{
		// 启动性能监视器
		mPerformace->start();
	}

	if (NULL != mContactService)
	{
		mContactService->startup();
	}

	// 创建本地端点实例
	if (NULL == mNative)
	{
		// TODO 获取 Talk Service 绑定地址
		Inet4Address address("127.0.0.1", mTalkService->getPort());
		mNative = CELL_NEW Endpoint(mTag, mConfig.role, address, 0);

		// 插入到云图中
		mCloudGraph->insert(mNative);
	}

	return true;
}
//-----------------------------------------------------------------------
void Nucleus::shutdown(void)
{
	mLoggerManager->log("");
	mLoggerManager->log("*-*-* Cell Finalizing *-*-*");

	// 从云图中移除自己
	if (NULL != mCloudGraph && NULL != mNative)
	{
		mCloudGraph->erase(mNative);
	}

	if (NULL != mPerformace)
	{
		mPerformace->stop();
		mPerformace->await();
	}

	if (mConfig.role & NucleusConfig::NODE)
	{
		mLoggerManager->log("Talk Service shutdown...");

		// 关闭 Talk 服务
		mTalkService->shutdown();

		// 停止 Cellet
		deactivateCellets();
	}

	if (mConfig.role & NucleusConfig::GATE)
	{
		// 关闭 Talk 服务
		mTalkService->shutdown();

		// 关闭代理
		mTalkService->stopProxy();
	}
	
	if (mConfig.role & NucleusConfig::CONSUMER)
	{
		// 关闭维护任务
		mTalkService->stopSchedule();
	}

	if (NULL != mContactService)
	{
		mContactService->shutdown();

		CELL_DELETE mContactService;
		mContactService = NULL;
	}

	unloadExternalLib();

	// 销毁对象

	if (NULL != mCelletSupervisor)
	{
		CELL_DELETE mCelletSupervisor;
		mCelletSupervisor = NULL;
	}

	if (NULL != mTalkService)
	{
		CELL_DELETE mTalkService;
		mTalkService = NULL;
	}

	if (NULL != mCloudGraph)
	{
		CELL_DELETE mCloudGraph;
		mCloudGraph = NULL;
	}

	if (NULL != mNative)
	{
		CELL_DELETE mNative;
		mNative = NULL;
	}

	if (NULL != mDynLibManager)
	{
		CELL_DELETE mDynLibManager;
		mDynLibManager = NULL;
	}

	if (NULL != mCryptology)
	{
		CELL_DELETE mCryptology;
		mCryptology = NULL;
	}

	if (NULL != mPerformace)
	{
		CELL_DELETE mPerformace;
		mPerformace = NULL;
	}

	if (NULL != mExecutorManager)
	{
		CELL_DELETE mExecutorManager;
		mExecutorManager = NULL;
	}

	if (NULL != mStorageEnumerator)
	{
		CELL_DELETE mStorageEnumerator;
		mStorageEnumerator = NULL;
	}

	if (NULL != mDialectEnumerator)
	{
		CELL_DELETE mDialectEnumerator;
		mDialectEnumerator = NULL;
	}

#ifdef CELL_CRASH_REPORT
	if (mCrashReport->available())
		mCrashReport->uninstall();
#endif // CELL_CRASH_REPORT
}
//-----------------------------------------------------------------------
const Performance* Nucleus::getPerformace(void) const
{
	return mPerformace;
}
//-----------------------------------------------------------------------
FORCEINLINE CloudGraph* Nucleus::getCloudGraph(void)
{
	return mCloudGraph;
}
//-----------------------------------------------------------------------
FORCEINLINE Endpoint* Nucleus::getNativeEndpoint(void)
{
	return mNative;
}
//-----------------------------------------------------------------------
void Nucleus::registerCellet(Cellet* cellet)
{
	Cellets::const_iterator iter = mCellets.find(cellet->getFeature().getIdentifier());
	if (iter != mCellets.end())
	{
		return;
	}

	mCellets.insert(Cellets::value_type(cellet->getFeature().getIdentifier(), cellet));
}
//-----------------------------------------------------------------------
void Nucleus::unregisterCellet(Cellet* cellet)
{
	Cellets::iterator iter = mCellets.find(cellet->getFeature().getIdentifier());
	if (iter != mCellets.end())
	{
		mCellets.erase(iter);
	}
}
//-----------------------------------------------------------------------
const Cellets& Nucleus::getCellets(void) const
{
	return mCellets;
}
//-----------------------------------------------------------------------
Cellet* Nucleus::getCellet(const String& identifier)
{
	Cellets::const_iterator iter = mCellets.find(identifier);
	if (iter != mCellets.end())
	{
		return iter->second;
	}
	return NULL;
}
//-----------------------------------------------------------------------
void Nucleus::activateCellets(void)
{
	mLoggerManager->log("Activates all cellets...");

	Cellets::const_iterator iter, end = mCellets.end();
	for (iter = mCellets.begin(); iter != end; ++iter)
	{
		iter->second->activate();

		mCelletSupervisor->registerCellet(iter->second);
	}
}
//-----------------------------------------------------------------------
void Nucleus::deactivateCellets(void)
{
	mLoggerManager->log("Deactivates all cellets...");

	Cellets::const_iterator iter, end = mCellets.end();
	for (iter = mCellets.begin(); iter != end; ++iter)
	{
		mCelletSupervisor->unregisterCellet(iter->second);

		iter->second->deactivate();
	}
}
//-----------------------------------------------------------------------
bool Nucleus::loadAdapter(DynLib* lib)
{
	// 检查输入的库是否已经存在，不允许重复添加
	if (std::find(mAdapterLibs.begin(), mAdapterLibs.end(), lib) == mAdapterLibs.end())
	{
		// 尝试获取启动符号
		DLL_START_ADAPTER pFunc = (DLL_START_ADAPTER)lib->getSymbol(START_ADAPTER_SYMBOL);
		if (!pFunc)
		{
			// 不是 Adapter 库
			return false;
		}

		mAdapterLibs.push_back(lib);

		// 调用启动函数
		pFunc();
		return true;
	}

	return false;
}
//-----------------------------------------------------------------------
void Nucleus::unloadAdapter(DynLib* lib)
{
	AdapterLibList::iterator iter = std::find(mAdapterLibs.begin(), mAdapterLibs.end(), lib);
	if (iter != mAdapterLibs.end())
	{
		// 调用终止函数
		DLL_STOP_ADAPTER pFunc = (DLL_STOP_ADAPTER)lib->getSymbol(STOP_ADAPTER_SYMBOL);
		if (pFunc)
			pFunc();
		// 移除
		mAdapterLibs.erase(iter);
	}
}
//-----------------------------------------------------------------------
bool Nucleus::loadCellet(DynLib* lib)
{
	// 检查输入的库是否已经存在，不允许重复添加
	if (std::find(mCelletLibs.begin(), mCelletLibs.end(), lib) == mCelletLibs.end())
	{
		// 尝试获取启动符号
		DLL_START_CELLET pFunc = (DLL_START_CELLET)lib->getSymbol(START_CELLET_SYMBOL);
		if (!pFunc)
		{
			// 不是 Cellet 库
			return false;
		}

		mCelletLibs.push_back(lib);

		// 调用启动函数
		pFunc();
		return true;
	}

	return false;
}
//-----------------------------------------------------------------------
void Nucleus::unloadCellet(DynLib* lib)
{
	CelletLibList::iterator iter = std::find(mCelletLibs.begin(), mCelletLibs.end(), lib);
	if (iter != mCelletLibs.end())
	{
		// 调用终止函数
		DLL_STOP_CELLET pFunc = (DLL_STOP_CELLET)lib->getSymbol(STOP_CELLET_SYMBOL);
		if (pFunc)
			pFunc();
		// 移除
		mCelletLibs.erase(iter);
	}
}
//-----------------------------------------------------------------------
void Nucleus::startSpinning(void)
{
	mSpinning = true;
	while (mSpinning)
	{
	#if CELL_PLATFORM == CELL_PLATFORM_WIN32
		Sleep(1000);
	#else
		sleep(1);
	#endif
	}
}
//-----------------------------------------------------------------------
void Nucleus::stopSpinning(void)
{
	mSpinning = false;
}
//-----------------------------------------------------------------------
void Nucleus::loadExternalLib(void)
{
	if (NULL == mDynLibManager)
	{
		return;
	}

	createDynLibBlacklist();

	namespace fs = boost::filesystem;
	fs::path curPath = fs::current_path();
	fs::directory_iterator end_itr; // default construction yields past-the-end
	for (fs::directory_iterator itr(curPath); itr != end_itr; ++itr)
	{
		String filename = itr->path().filename().string();

	#if CELL_PLATFORM == CELL_PLATFORM_WIN32
		if (StringUtil::endsWith(filename, "dll", true))
	#else
		if (StringUtil::endsWith(filename, "so", true))
	#endif
		{
			// 跳过黑名单里的库名
			if (existDynLibBlacklist(filename))
			{
				continue;
			}

			// 加载动态库
			DynLib* lib = mDynLibManager->load(itr->path().filename().string());
			if (lib == NULL)
				continue;

			if (false == loadCellet(lib))
			{
				if (false == loadAdapter(lib))
				{
					// 既不是 Adapter 也不是 Cellet，则卸载该库
					mDynLibManager->unload(lib);
				}
			}
		}
	}

	destroyDynLibBlacklist();
}
//-----------------------------------------------------------------------
void Nucleus::unloadExternalLib(void)
{
	if (NULL == mDynLibManager)
	{
		return;
	}

	AdapterLibList::iterator aiter, aend = mAdapterLibs.end();
	for (aiter = mAdapterLibs.begin(); aiter != aend; ++aiter)
	{
		DynLib* lib = (*aiter);
		DLL_STOP_ADAPTER pFunc = (DLL_STOP_ADAPTER)lib->getSymbol(STOP_ADAPTER_SYMBOL);
		if (pFunc)
			pFunc();
		mDynLibManager->unload(lib);
	}
	mAdapterLibs.clear();

	CelletLibList::iterator citer, cend = mCelletLibs.end();
	for (citer = mCelletLibs.begin(); citer != cend; ++citer)
	{
		DynLib* lib = (*citer);
		DLL_STOP_CELLET pFunc = (DLL_STOP_CELLET)lib->getSymbol(STOP_CELLET_SYMBOL);
		if (pFunc)
			pFunc();
		mDynLibManager->unload(lib);
	}
	mCelletLibs.clear();
}
//-----------------------------------------------------------------------
void Nucleus::createDynLibBlacklist(void)
{
	mDynLibBlacklist.push_back("nucleus");
	mDynLibBlacklist.push_back("CrashRpt");
	mDynLibBlacklist.push_back("dbghelp");
	mDynLibBlacklist.push_back("msvc");
	mDynLibBlacklist.push_back("mfc");
	mDynLibBlacklist.push_back("wxbase");
	mDynLibBlacklist.push_back("wxmsw");
}
//-----------------------------------------------------------------------
void Nucleus::destroyDynLibBlacklist(void)
{
	mDynLibBlacklist.clear();
}
//-----------------------------------------------------------------------
bool Nucleus::existDynLibBlacklist(const String& filename)
{
	DynLibBlacklist::const_iterator iter, end = mDynLibBlacklist.end();
	for (iter = mDynLibBlacklist.begin(); iter != end; ++iter)
	{
		if (StringUtil::startsWith(filename, (*iter)))
		{
			return true;
		}
	}
	return false;
}


//-----------------------------------------------------------------------
void initializeSock(void)
{
	::WSADATA wsaData = {0};
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) == SOCKET_ERROR)
	{
		LoggerManager::getSingleton().log("Unable to load Winsock 2.2");

		if (WSAStartup(MAKEWORD(2, 0), &wsaData) == SOCKET_ERROR)
		{
			LoggerManager::getSingleton().log("Unable to load Winsock 2.0");
		}
	}
}
//-----------------------------------------------------------------------
void finalizeSock(void)
{
	::WSACleanup();
}

} // end namespace cell
